<!DOCTYPE html>
<!-- saved from url=(0045)https://js13kgames.com/games/choch/index.html -->
<html lang="en" style="font-size: 10px;"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>JS13K-2020</title><style type="text/css">body { 
            margin: 0;
            overflow: hidden;
            padding: 0;
        }
        #glcanvas {
            position: absolute;
        }
        #canvas2d {
           display: none;
        }</style><script charset="utf-8" src="chrome-extension://pngicgippofneelinabebobnkpmdiphn/js/btype.js"></script><script type="text/javascript" charset="utf-8" src="chrome-extension://pngicgippofneelinabebobnkpmdiphn/js/chrome.js"></script></head><body><canvas id="glcanvas" width="1536" height="722"></canvas><canvas id="canvas2d" width="1536" height="722"></canvas><script>const vsSource="\nprecision mediump float;\nattribute vec2 aPos;void main(){gl_Position=vec4(aPos,0.,1.);}\n",gameFsSource="\nprecision mediump float;\nuniform float t;uniform vec2 res,pos,speed;uniform vec4 cam;const float y=.03;const vec2 v=vec2(1.,2.5),m=vec2(sqrt(3.)/2.,.5),f=vec2(-sqrt(3.)/2.,.5);const vec3 s=vec3(.5,9.,.4),a=s/5.,I=vec3(3.5,.5,.1)/2.,d=I/6.,x=vec3(.8,.8,1.),r=vec3(.03),l=vec3(.07,.07,.13);\n#define PI 3.14159265\n#define LAYERS 6.0\n#define NOISE_AMP 0.0\nfloat n(float v){return fract(sin(v)*31345.2);}float i(vec2 v){return n(dot(v,vec2(43.123,32.1235)));}float p(float v){return mix(n(floor(v)),n(floor(v)+1.),smoothstep(0.,1.,fract(v)));}mat2 P(float v){float y=sin(v),x=cos(v);return mat2(x,y,-y,x);}float P(vec2 v,vec2 y){vec2 m=abs(v)-y;return length(max(m,0.))+min(max(m.x,m.y),0.);}float i(vec2 v,float y){return length(v)-y;}float n(vec2 v,vec2 m){return min(P(v,m),P(v,m.yx));}struct MapValue{float solid;float deadly;float checkpoint;float checkpointId;};\n#define INF 1e10\nfloat h(vec2 v){vec2 y=v-vec2(-.3,-.4);y*=P(t);float f=n(y,vec2(.05,.45));y=v-vec2(.3,.1);y*=P(-t+PI/4.);f=min(f,n(y,vec2(.05,.45)));y=v-vec2(-.3,.7);y*=P(t+PI/8.);f=min(f,n(y,vec2(.05,.45)));return f;}float c(vec2 v){float y=.5;vec2 i[3];i[0]=vec2(0.,1.);i[1]=m;i[2]=f;float r=INF;for(int x=0;x<3;++x){float s=dot(v,i[x])+t/32.,a=abs(mod(s,y)-y/2.),d=floor(s*y),l=sin(t*2.+s*2.+.66*PI*float(x));r=min(r,a+y/16.*(l+.5));}return r;}float w(vec2 v){float y=10.,m=sin(v.x*y)*sin(v.y*y)+.7*sin(2.*t+5.*v.y+10.*v.x)+.5;return m/y;}float e(vec2 v){float y=10.,m=sin(v.x*y)*sin(v.y*y+t/3.)+.7*sin(2.*t+5.*v.y+sin(.3*t))+.4;return m/y;}float M(vec2 v){v=vec2(length(v),atan(v.y,v.x));float y=.3,x=PI/6.,m=v.x-t/6.,s=mod(floor(m/y),2.)==0.?-1.:1.,f=(abs(mod(v.y+t/4.*s,x)-y/2.)-x/4.)*v.x,i=max(abs(mod(m,y)-y/2.)-y/10.,f);return i;}float N(vec2 v){float y=dot(v,v);v/=y;vec2 m=vec2(1.,2.5);v.y+=.45*t;vec2 f=floor(v/m);v.x+=.7*t*mix(-1.,1.,mod(f.y,2.));vec2 s=abs(mod(v,m)-m/2.)-m/2.5;f=floor(v/m);float x=step(.5,mod(f.x+f.y,2.)),i=mix(max(s.x,s.y),1000.,x);return i*y;}float L(vec2 v){float y=0.;const float m=4.;for(float f=0.;f<m;++f){vec2 i=vec2(0.,mix(-.9,.9,f/(m-1.)));i.y+=.22*sin(t+PI/2.*f);i.x+=.1*sin(t+PI/3.*f);y+=1./length(v-i);}float f=1./y,x=.03,i=max(.09-f,abs(mod(f-t/30.,x)-x/2.)-x/2.3);return i;}float o(vec2 v){float y=.3,m=(sin(t)+1.)/2.;v.y-=t/6.;v.x+=m*p(v.y*5.+123.+t)*.5;v.y+=m*p(v.x*5.+.4*t)*.4;return abs(mod(v.y,y)-y/2.)-y/20.;}float u(vec2 v){const float y=3.;for(float f=0.;f<y;++f)v.x=abs(v.x),v.x-=.3,v.y-=.1,v=v*P(2.*PI/y);float m=.4;v.y-=t/10.;v.x-=t/20.;vec2 f=abs(mod(v,m)-m/2.)-m/3.;return max(f.x,f.y);}float g(vec2 v){const float y=6.;for(float f=0.;f<y;++f)v.x=abs(v.x),v.x-=.3,v.y+=.1,v*=P(2.*PI/y);v*=P(PI/3.);float m=.4;v.y-=t/10.;v.x-=t/20.;vec2 f=abs(mod(v,m)-m/2.)-m/3.;return max(f.x,f.y);}float b(vec2 v){vec2 y=vec2(.2),f=mod(v,y)-y/2.,m=floor(v/y),s=vec2(0.),x=vec2(5.,30.);m.x+=.5;float i=.5+(.25*sin(m.y-t)+.75*sin(.8*m.x+2.*sin(t)))*.5;f*=P((1.-i)*PI);return P(f,mix(vec2(-.05),y/2.1,i));}float F(vec2 v){float y=.4;v*=P(PI/4.);v.x+=y/2.;vec2 f=mod(v,y)-y/2.,m=floor(v/y),s=vec2(y/32.,y/2.3);float x=i(f,mix(s.x,s.y,sin(t)*.5+.5));f=mod(v+y/2.,y)-y/2.;float a=i(f,mix(s.x,s.y,sin(t+PI)*.5+.5));return min(x,a);}float C(vec2 v){float y=.15;vec2 f=vec2(0.,mod(v.y,y)-y/2.);float m=floor(v.y/y);f.x=abs(v.x+.1*sin(m+t/4.));float i=.5+m*y*3.;return max(abs(f.y)-y/3.,.2+.2*sin(i*t+123.)-f.x);}float k(vec2 v){float y=.103;vec2 f=vec2(v.x,mod(v.y,y)-y/2.);float m=floor(v.y/y),s=.5+m;return P(f-vec2(.41*sin(10.*m+t),0.),vec2(.1,y/2.2));}float V(vec2 v){const float y=3.;v.x*=v.y>0.?1.:-1.;v.y=abs(v.y);v.y-=.6;float f=smoothstep(0.,1.,fract(t))*2.*PI/y;v*=P(f);vec2 m=vec2(length(v),atan(v.y,v.x));m.y=mod(m.y,2.*PI/y)-PI/y;v=vec2(m.x*cos(m.y),m.x*sin(m.y))-vec2(.37,0.);v*=P(-y*f);return P(v,vec2(.06));}float S(vec2 v){float y=INF,m=.06;for(float f=0.;f<3.;++f){float s=.2*(f+1.);vec2 x=v;float i=floor(2.*s/m)+3.,I=2.*PI/i;vec2 r=vec2(length(x),atan(x.y,x.x)+I/2.);float a=floor(r.y/I);if(abs(a)>=i/2.)a=abs(a);r.y=mod(r.y,I)-I/2.;x=vec2(r.x*cos(r.y),r.x*sin(r.y))-vec2(s,0.);vec2 e=vec2(m);e*=mix(-.3,.7,smoothstep(-.4,.4,sin(a+t)));y=min(y,P(x,e));}return y;}float E(vec2 v){float y=1.,s=3.,f=p(v.y*s+123.*floor(y*t)-t),x=p(v.y*s+123.*floor(y*t+1.)-t);v.x+=.3*(mix(f,x,smoothstep(0.,1.,fract(y*t)))-.5);float i=.2,a=abs(mod(dot(v-t/30.,m),i)-i/2.)-i/2.1;return max(.1-abs(v.x),a);}vec2 A(vec2 v){float y=1.5,m=.3;vec2 f=v;f.y+=.5*y*step(0.,f.x);f.y=mod(f.y,y)-y/2.;f.x=abs(f.x);float i=abs(v.x)-m;i=min(i,P(f-vec2(m+.03,0.),vec2(.1)));vec2 r=v;r.y=mod(r.y+.5,y/2.)-y/4.;vec2 x=mix(vec2(.1),vec2(.29,.5),smoothstep(.1,.5,sin(t*1.2)));float s=P(r,x);return vec2(-i,s);}vec2 z(vec2 v){float y=8.;v.y+=.7;v*=y;v.x+=1.8;float f=P(v,vec2(.8,1.));f=max(f,-P(v-vec2(-.5,.4),vec2(.4,.1)));f=max(f,-P(v-vec2(.5,-.2),vec2(.4,.1)));f=min(f,P(v-vec2(1.8,0.),vec2(.8,1.)));f=max(f,-P(v-vec2(1.8,0.),vec2(.1,.5)));f=min(f,P(v-vec2(3.6,0.),vec2(.8,1.)));f=max(f,-P(v-vec2(3.6,0.),vec2(.1,.5)));return vec2(f/y,255.);}MapValue Y(vec2 y){float f=floor(y.y/v.y);ivec2 m=ivec2(floor(y/v));vec2 x=mod(y,v)-v/2.;MapValue s;bool r=true;vec4 a=vec4(INF,INF,INF,0.);if(m.x==0){if(m.y==0)a.y=h(x);else if(m.y==1)a.y=L(x);else if(m.y==2)a.y=S(x);else if(m.y==3)a.y=E(x);else if(m.y==4)a.y=F(x);else if(m.y==5)a.xy=A(x);else if(m.y==6)a.y=e(x);else if(m.y==7)a.y=M(x);else if(m.y==8)a.y=b(x);else if(m.y==9)a.y=k(x);else if(m.y==10)a.y=u(x);else if(m.y==11)a.y=V(x);else if(m.y==12)a.y=C(x);else if(m.y==13)a.y=w(x);else if(m.y==14)a.y=o(x);else if(m.y==15)a.y=c(x);else if(m.y==16)a.y=g(x);else if(m.y==17)a.y=N(x);else if(m.y==18)a.zw=z(x);else r=false;}else r=false;MapValue d=MapValue(-INF,a.y,0.,0.);vec2 I=v/2.2;float l=.1;if(r){float p=P(x,I);vec2 n=vec2(x.x,abs(x.y)-I.y);float Y=max(p,-i(n,l));d.deadly=max(d.deadly,Y);d.solid=min(-p,a.x);}vec2 p=vec2(-1.,19.*v.y);p=vec2((p.x+p.y)/2.,(p.y-p.x)/2.);float n=P(y-vec2(.5,p.x),vec2(l,p.y));d.solid=max(d.solid,-n);float Y=mod(y.y+v.y/2.,v.y)-v.y/2.;vec2 R=vec2(abs(Y)-.03,floor((y.y+v.y/2.)/v.y));R=mix(R,a.zw,step(a.z,R.x));d.checkpoint=R.x;d.checkpointId=R.y;return d;}vec2 R(vec2 v){vec2 y=vec2(.001,0.);float x=Y(v).solid;return normalize(vec2(Y(v+y.xy).solid-x,Y(v+y.yx).solid-x));}float A(float v,float y){return pow(.001*y/abs(v),2.5);}float q(vec2 v){v*=mat2(sqrt(3.)/2.,-.5,0.,1.);float y=0.;const float f=3.;for(float m=0.;m<f;++m){float x=40.+37.*m;vec2 i=v*x+t/x,s=floor(i),a=fract(i);if(a.x+a.y>1.)a=1.-a,s+=.5;float r=.03;y+=max(step(a.x,r),max(step(a.y,r),step(1.-a.x-a.y,r)))*smoothstep(.6,.95,p(.6*s.x+.5*s.y+.3*t+3.*m))*mix(1.,.3,m/(f-1.));}return y;}vec4 O(vec2 v){MapValue m=Y(v);vec3 f=vec3(0.);if(m.solid>0.){f+=A(m.checkpoint,3.)*s;if(m.checkpoint<0.)f+=a;else{f+=A(m.deadly,3.)*I;if(m.deadly<0.)f+=d;}}f+=x*A(m.solid,2.);return vec4(f,m.solid);}float A(in vec2 v,in vec2 y,in vec2 m){vec2 f=v-y,x=m-y;float i=clamp(dot(f,x)/dot(x,x),0.,1.);return length(f-x*i);}float C(vec2 v,float y){return max(0.,length(v)-y);}float Z(vec2 v){float m=y,f=0.,x=atan(speed.y,speed.x),s=m/3.;vec2 i=v-vec2(0.,(sin(4.*t)+1.)*m/16.+m/3.);f+=pow(m/100./C(i,s),2.);vec2 r=vec2(cos(x),sin(x));for(float a=0.;a<8.;++a){float d=mix(-PI/4.,PI/4.,mod(a,4.)/3.)+step(4.,a)*PI-PI/2.+x;vec2 e=.9*m*vec2(cos(d),sin(d));e+=m*.1*r*sin(20.*t+(mod(a,2.)==0.?PI:0.))*length(speed);vec2 p=v;float I=clamp(0.,1.,length(v)/m);p.y-=.01*(I-I*I);f+=A(A(p,v-i,-e),I*2.);}f=min(1.,f);i*=P(x);i.y=abs(i.y);f-=pow(m/100./C(i-vec2(1.,0.)*s*.7-vec2(0.,1.)*s*.3,m/40.),2.);return f;}vec3 X(vec2 v){vec3 f=vec3(0.);v/=cam.zw;for(float y=0.;y<LAYERS;++y){float x=y/LAYERS*.04;vec2 m=v*(1.-x)-vec2(0.,x)+vec2(i(v+y+t)-.5,i(1.3*v+y+1.4*t)-.5)*NOISE_AMP;m=m+cam.xy;vec4 a=O(m);f+=a.xyz/LAYERS;if(y==0.&&a.w<0.)f+=r*q(v+cam.xy/5.);}f+=Z(v+cam.xy-pos);return f;}void main(){if(gl_FragCoord.x<1.&&gl_FragCoord.y<1.){float v=Y(pos).solid;gl_FragColor=vec4(v<y?vec3(1.,.5*(R(pos)+1.)):vec3(0.),1.);}else if(gl_FragCoord.x<2.&&gl_FragCoord.y<1.)gl_FragColor=vec4(vec3(Y(pos).deadly<y/2.?1.:0.),1.);else if(gl_FragCoord.x<3.&&gl_FragCoord.y<1.){MapValue v=Y(pos);gl_FragColor=vec4(v.checkpoint<0.?vec3(1.,v.checkpointId/255.,0.):vec3(0.),1.);}else{vec2 v=2.*gl_FragCoord.xy/res-1.;v.x*=res.x/res.y;vec3 m=X(v);gl_FragColor=vec4(l+sqrt(m),1.);}}\n",postprocFsSource="\nprecision mediump float;\nuniform vec2 res;uniform sampler2D tex;uniform vec3 fact;void main(){vec2 t=gl_FragCoord.xy/res,r=abs(t*2.-1.);float x=.003+.015*fact.x;vec3 s=vec3(texture2D(tex,t-vec2(x,0.)).x,texture2D(tex,t).y,texture2D(tex,t+vec2(x,0.)).z);float v=.6,f=max(smoothstep(1.-v,1.,r.x),smoothstep(1.-v,1.,r.y));gl_FragColor=vec4(mix(s,vec3(0.),.25*f)+vec3(0.,fact.y,0.)+fact.z,1.);}\n",canvasPostprocFsSource="\nprecision mediump float;\nuniform vec2 res;uniform sampler2D tex;uniform float t,ef;const vec3 v=vec3(.07,.07,.13),s=vec3(.6);vec4 p(vec2 v){if(v.x<0.||v.x>1.||v.y<0.||v.y>1.)return vec4(0.);vec2 m=abs(2.*v-1.),p=vec2(.02,.002),r=p*res.y/res.x;float x=max(smoothstep(1.-r.x-2.*r.y,1.-r.x-r.y,m.x),smoothstep(1.-p.x-2.*p.y,1.-p.x-p.y,m.y))*smoothstep(1.,1.-r.y,m.x)*smoothstep(1.,1.-p.y,m.y);vec4 a=texture2D(tex,.96*v-.02);float f=1.5,y=1.-.1*(sin((v.y+t/20.)*300.)+1.);return vec4(max(a.xyz,vec3(s*x)),max(a.w,x)*y);}vec2 x(vec2 v){float m=.05;v=2.*v-1.;return(vec2(v.x*(1.+m*pow(abs(v.y),2.)),v.y*(1.+m*pow(abs(v.x),2.)))+1.)/2.;}vec3 m(vec2 x){vec4 m=p(x)+.2*p((x-.5)*.99+.5);return mix(v,m.xyz,m.w);}void main(){vec2 v=gl_FragCoord.xy/res;v.y=1.-v.y;v=1.04*v-.02;v=x(v);const float y=.002;vec3 a=vec3(m(v-vec2(y,0.)).x,m(v).y,m(v+vec2(y,0.)).z);gl_FragColor=vec4(a+ef,1.);}\n";class Vec2{constructor(e,t){this.x=e,this.y=t}addEq(e,t){this.x+=e,this.y+=t}mulEqScalar(e){this.x*=e,this.y*=e}mul(e){return new Vec2(this.x*e,this.y*e)}mixEq(e,t,a){this.x=this.x*(1-a)+e*a,this.y=this.y*(1-a)+t*a}len(){return Math.sqrt(this.x*this.x+this.y*this.y)}dot(e){return this.x*e.x+this.y*e.y}set(e,t){this.x=e,this.y=t}}function initScreenQuadBuffer(e){const t=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,t);return e.bufferData(e.ARRAY_BUFFER,new Float32Array([1,1,-1,1,1,-1,-1,-1]),e.STATIC_DRAW),t}function initShaderProgram(e,t,a){function o(e,t,a){const o=e.createShader(t);return e.shaderSource(o,a),e.compileShader(o),o}const n=o(e,e.VERTEX_SHADER,t),c=o(e,e.FRAGMENT_SHADER,a),r=e.createProgram();return e.attachShader(r,n),e.attachShader(r,c),e.linkProgram(r),r}function createPostprocTexture(e,t,a){let o=e.createTexture();return e.bindTexture(e.TEXTURE_2D,o),t>0&&a>0&&e.texImage2D(e.TEXTURE_2D,0,e.RGBA,t,a,0,e.RGBA,e.UNSIGNED_BYTE,null),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),o}function createFramebufferWithTexture(e,t,a,o){o&&e.deleteTexture(o[1]);let n=createPostprocTexture(e,t,a),c=o?o[0]:e.createFramebuffer();return e.bindFramebuffer(e.FRAMEBUFFER,c),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,n,0),[c,n,t,a]}var combFilterTunings=[1557,1617,1491,1422,1277,1356,1188,1116].map(e=>e/44100),allpassFilterFrequencies=[225,556,441,341];function LowpassCombFilter(e){var t=e.createDelay(1),a=e.createBiquadFilter();a.Q.value=-3.0102999566398125,a.type="lowpass",t.dampening=a.frequency;var o=e.createGain();return t.resonance=o.gain,t.connect(a),a.connect(o),o.connect(t),t.dampening.value=3e3,t.delayTime.value=.1,t.resonance.value=.5,t}function Freeverb(e){var t=e.createGain();t.channelCountMode="explicit",t.channelCount=2;var a=e.createGain(),o=e.createChannelMerger(2),n=e.createChannelSplitter(2),c=e.createBiquadFilter();c.type="highpass",c.frequency.value=200;var r=e.createGain(),i=e.createGain();t.connect(i),t.connect(r),r.connect(n),o.connect(c),c.connect(a),i.connect(a);for(var l=[],s=[],f=[],v=.8,m=3e3,y=0;y<allpassFilterFrequencies.length;y++){var u=e.createBiquadFilter();u.type="allpass",u.frequency.value=allpassFilterFrequencies[y],s.push(u),s[y-1]&&s[y-1].connect(u)}for(var x=0;x<allpassFilterFrequencies.length;x++){var d=e.createBiquadFilter();d.type="allpass",d.frequency.value=allpassFilterFrequencies[x],f.push(d),f[x-1]&&f[x-1].connect(d)}s[s.length-1].connect(o,0,0),f[f.length-1].connect(o,0,1);for(var p=0;p<combFilterTunings.length;p++){var g=LowpassCombFilter(e);g.delayTime.value=combFilterTunings[p],p<combFilterTunings.length/2?(n.connect(g,0),g.connect(s[0])):(n.connect(g,1),g.connect(f[0])),l.push(g)}return Object.defineProperties(t,{roomSize:{set:e=>{v=e,T()}},dampening:{set:e=>{m=e,T()}}}),T(),t.connect=a.connect.bind(a),t.disconnect=a.disconnect.bind(a),t.wet=r.gain,t.dry=i.gain,t.combFilters=l,t;function T(){for(var e=0;e<l.length;e++)l[e].resonance.value=v,l[e].dampening.value=m}}function setupAudioProcessor(){let e=new AudioContext,t=t=>e.currentTime+t,a=Freeverb(e);a.roomSize=.7,a.dampening=4e3,a.wet.value=.5,a.dry.value=0,a.connect(e.destination);let o=(e,a,o,n=1,c=0)=>{e.linearRampToValueAtTime(n,t(a)),e.linearRampToValueAtTime(c,t(a+o))},n=(a,o)=>{let n=e.createOscillator();n.type="sine",n.frequency.value=a;let c=e.createOscillator();c.type="sine",c.frequency.value=o;let r=e.createGain();r.gain.setValueAtTime(0,t(0));let i=e.createGain();return i.gain.setValueAtTime(0,t(0)),n.connect(r),c.connect(r.gain),r.connect(i),n.start(),c.start(),[n,c,i]},c=Array(3).fill().map(()=>{let[,,a]=n(834,1147),c=e.createBiquadFilter();return c.Q.setValueAtTime(5,t(0)),c.frequency.setValueAtTime(2500,t(0)),c.type="bandpass",a.connect(c),c.connect(e.destination),()=>{o(a.gain,.01,.1)}}),r=0,i=(()=>{let[t,a,c]=n(0,0);return c.connect(e.destination),e=>{t.frequency.value=e,a.frequency.value=1.33*e,o(c.gain,.01,.1)}})(),l=(()=>{let[c,r,i]=n(0,0),l=e.createDelay(.45);l.delayTime.setValueAtTime(.45,t(0));let s=e.createGain();s.gain.setValueAtTime(.5,t(0)),i.connect(l),l.connect(s),s.connect(l),i.connect(a),s.connect(a);let f=[440,220,440],v=e=>{c.frequency.setValueAtTime(f[e],t(0)),r.frequency.setValueAtTime(.75*f[e],t(0))};return()=>{o(i.gain,0,.5),v(0),setTimeout(()=>v(1),112.5),setTimeout(()=>v(2),225)}})(),s=(()=>{let n=e.createGain();n.gain.setValueAtTime(0,t(0));for(let t=-1;t<=1;++t){let a=e.createOscillator();a.type="sawtooth",a.frequency.value=55*Math.pow(2,20*t/1200),a.start(),a.connect(n)}let c=e.createBiquadFilter();return c.Q.setValueAtTime(1,t(0)),c.frequency.setValueAtTime(1e3,t(0)),c.type="lowpass",n.connect(c),c.connect(a),c.connect(e.destination),()=>{o(n.gain,.01,.5)}})(),f=(()=>{let o=e.createDelay(1);o.delayTime.setValueAtTime(1,t(0));let n=e.createGain();n.gain.setValueAtTime(.8,t(0));let c=e.createGain();c.gain.setValueAtTime(0,t(0));let r=Array(3).fill().map(a=>{let o=e.createOscillator();o.frequency.value=.1+.1*Math.random(),o.type="sine",o.start();let n=e.createGain();n.gain.setValueAtTime(10,t(0)),o.connect(n);let r=e.createGain(),i=e.createOscillator();i.frequency.value=.05+.05*Math.random(),i.type="sine",i.start();let l=e.createOscillator();return l.type="sine",l.start(),i.connect(r.gain),n.connect(l.detune),l.connect(r),r.connect(c),l});c.connect(o),o.connect(n),n.connect(o),o.connect(a);let i=[[0,5,9],[3,10,12],[2,5,7],[0,3,10],[5,7,10],[0,2,7]],l=-1,s=e=>{for(let a=0;a<r.length;++a)r[a].frequency.setValueAtTime(220*Math.pow(2,e[a]/12),t(0))},f=()=>{l=(l+1)%i.length;let e=i[l];s(e)};return setInterval(()=>{let e=i[l].map(e=>e+12*(Math.floor(3*Math.random())-1));s(e)},2e3),f(),[e=>{e?c.gain.linearRampToValueAtTime(.05,t(5)):(c.gain.cancelScheduledValues(t(0)),c.gain.setValueAtTime(0,t(0)))},f]})();return{ctx:e,startTime:t(0),typingFn:()=>{c[++r%c.length]()},menuChangeFn:e=>{i(e?550:660)},checkpoint:()=>{l(),f[1]()},death:s,ambient:f}}let audioProcessor=null;function getAudioProcessor(){return audioProcessor||(audioProcessor=setupAudioProcessor()),audioProcessor}async function print_2d(c,text,em,cancelFn,textUpdatedCb,typingCb){let print,ms=0,w="+",tail=text.shift(),[x,y]=[0,0],font,color="#9c4",typing=!0,n={valueOf(){y+=1.4*em,x=1*em}},wait=e=>new Promise(t=>setTimeout(t,e));for(;tail;){if(cancelFn())return;if(tail.startsWith("!"))eval(tail.substring(1)),tail="";else if(tail.startsWith("_"))await wait(tail.substring(1)),tail="";else for(;tail;){if(await wait(ms),cancelFn())return;[_,print,tail]=tail.match(`(^.${w})(.+)?`)," "!==print&&typingCb(),c.font=font,c.shadowColor=(c.fillStyle=color)+"b",c.shadowBlur=12,c.fillText(print,x,y),textUpdatedCb(),x+=c.measureText(print).width}tail&&0!=tail.length||(tail=text.shift())}}let cliFont="bold 1.4rem 'Andale Mono', 'Courier New', monospace",dialogFont="bold italic 2rem 'Lucida Sans Unicode', 'Lucida Grande', sans-serif",logoFont="bold 6rem Impact, Charcoal, sans-serif",startCutsceneData=(e,t)=>[`!n+n;ms=50;font="${cliFont}";color='#9c4'`,"[totosz@vlt1337 ~]$ ","_500","!color='#ccc';w=''","hack https://asodih90xvy809.com/90as8y/","!+n;ms=300",". . .  ","!n+n;color='#999';ms=50;w='+'","HTTP/2 404","!+n","content-type: text/html","!+n","content-length: 1565","!+n","date: "+(new Date).toDateString(),"!n+n","<!DOCTYPE html>","!+n","<html lang=en>","!+n","<title>Error 404 (Not Found)!!1</title>","!+n","<p>The requested URL was not found on this server. Tough luck :-)","!n+n,ms=500;color='#f83'","[ERROR] Hacking failed with code 0x04729632","!+n;color='#9c4'","[totosz@vlt1337 ~]$ ","!x_=x;y_=y","_1200",`!;y=${t}-6*em;x=17*em;ms=60;w='';color='#baa';font="${dialogFont}"`,"@#$%! *They* moved the page again.","!+n","_800",`!;c.fillStyle='#000';c.shadowBlur=0;c.clearRect(0,y-4*em,${e},${t})`,`!;ms=60;y=${t}-6*em;x=17*em`,"You can hide it but I'll find it anyway!","_800",`!;c.fillStyle='#000';c.shadowBlur=0;c.clearRect(0,y-4*em,${e},${t})`,`!;x=x_;y=y_;ms=50;color='#ccc';w='';font="${cliFont}"`,"./choch https://asodih90xvy809.com/ --find-missing-page","!;ms=800"," ","!;ms=50","--please","_400",`!;c.fillStyle='#000';c.shadowBlur=0;c.clearRect(0,0,${e},${t});y=2.5*em`,"!n+n;ms=500;w='+',color='#fff'","Initialize crawler ","!;x=42*em;color='#9c4'","[ OK ]","!+n;color='#fff'","Generate search route ","!;x=42*em;color='#9c4'","[ OK ]","!+n;color='#fff'","Calculate expression matcher ","!;x=42*em;color='#9c4'","[ OK ]","!+n;color='#fff'","Perform automated search ","_500","!;x=42*em;color='#f83'","[FAIL]","!n+n;color='#fff';x=13*em","Manual guidance required. Press enter to start","!w='';ms=200",". . .  "],endCutsceneData=(e,t)=>[`!n+n;ms=50;font="${cliFont}";color='#9c4';w='+'`,"[totosz@vlt1337 ~]$ ","_1000","!color='#ccc';w=''","hack https://asodih90xvy809.com/90as8y/","!+n;ms=300",". . .  ","!n+n;color='#ccc';ms=50;w='+'","HTTP/2 ","!color='#fff'","200 OK","!+n;color='#ccc'","content-type: text/html","!+n","content-length: 2273","!+n","date: "+(new Date).toDateString(),"!n+n","<!DOCTYPE html>","!+n","<html lang=en>","!+n","<title>Hello there!</title>","!+n","<p>You're welcome!</p>","_500","!n+n;color='#9c4'","[totosz@vlt1337 ~]$ ","_1200",`!;y=${t}-6*em;x=24*em;ms=60;w='';color='#f80';font="${dialogFont}"`,"Finally... I found it.","_3000",`!c.clearRect(0,0,${e},${t});y=2.5*em;+n;ms=50;font="${cliFont}";color='#9c4'`,"CHOCH","_1500","!+n;color='#ccc'","A game by ","!color='#f22'","kostik1337","!color='#ccc'"," & ","!color='#44f'","lampysprites","_400","!n+n;color='#ccc'","Thank you for playing!","_10000"];const STATE_MENU=0,STATE_START_CUTSCENE=1,STATE_GAME=2,STATE_END=3;let gameState=-1,player={},gameSettings={difficulty:1,graphics:2,difficultyVariants:["very easy","easy","normal","hardcore"],graphicsVariants:["low","medium","high"],currentSelection:0};function init(e,t){ctx.time=0;let a=initShaderProgram(e,vsSource,gameFsSource),o=t=>e.getUniformLocation(a,t);ctx.programInfo={program:a,uTime:o("t"),uRes:o("res"),uPos:o("pos"),uCam:o("cam"),uSpeed:o("speed")},a=initShaderProgram(e,vsSource,postprocFsSource),o=t=>e.getUniformLocation(a,t),ctx.postprocProgramInfo={program:a,uRes:o("res"),uTex:o("tex"),uFactors:o("fact")},ctx.canvasTex=createPostprocTexture(e,0,0),a=initShaderProgram(e,vsSource,canvasPostprocFsSource),o=t=>e.getUniformLocation(a,t),ctx.canvasPostprocProgramInfo={program:a,uRes:o("res"),uTex:o("tex"),uTime:o("t"),uEndFactor:o("ef")},e.bindBuffer(e.ARRAY_BUFFER,t);const n=e.getAttribLocation(a,"aPos");e.vertexAttribPointer(n,2,e.FLOAT,!1,0,0),e.enableVertexAttribArray(n),setState(STATE_MENU)}function recreateGameFramebufferAndTex(){let e=[4,2,1][gameSettings.graphics];ctx.fbTexData=createFramebufferWithTexture(ctx.gl,canvasW()/e,canvasH()/e,ctx.fbTexData)}function setState(e){gameState=e,e==STATE_MENU?(audioProcessor&&audioProcessor.ambient[0](!1),updateMenuCanvas()):e==STATE_START_CUTSCENE?showCutscene(startCutsceneData,STATE_START_CUTSCENE):e==STATE_END?showCutscene(endCutsceneData,STATE_END):e==STATE_GAME&&(ctx.time=0,audioProcessor&&audioProcessor.ambient[0](!0),recreateGameFramebufferAndTex(),player={pos:new Vec2(0,0),cam:new Vec2(0,0),maxVelocity:.005,reqSpeed:new Vec2(0,0),speed:new Vec2(0,0),movementStates:[0,0,0,0],lastCheckpointId:-1,lastCheckpointPos:new Vec2(.5,-.9),isDead:!1,deathFactor:0,checkpointFactor:0,endFactor:0,isEnd:!1,solidNormal:null},playerResurrect(),player.cam.set(player.pos.x,player.pos.y))}function playerResurrect(){player.isDead=!1,player.deathFactor=0,player.speed.set(0,0),player.pos.set(player.lastCheckpointPos.x,player.lastCheckpointPos.y)}function update(){if(joy&&joyInput(joy,onKeyEvent),gameState!=STATE_GAME)return void(player&&(player.endFactor*=.99));if(player.isDead)player.speed.set(0,0);else if(player.speed.mixEq(player.reqSpeed.x,player.reqSpeed.y,.3),player.pos.addEq(player.speed.x,player.speed.y),null!=player.solidNormal){let e=player.solidNormal.dot(player.speed);if(e<0){let t=player.solidNormal.mul(1*-e);player.pos.addEq(t.x,t.y)}}player.cam.mixEq(player.pos.x+0*player.speed.x,player.pos.y+0*player.speed.y,.1),player.deathFactor*=.92,player.checkpointFactor*=.95,player.isEnd&&(player.endFactor+=.03*(1-player.endFactor),player.endFactor>.99&&setState(STATE_END))}function render(e){let t=[1/80,1/70,1/60,.02][gameSettings.difficulty];if(ctx.time+=t,gameState==STATE_MENU||gameState==STATE_START_CUTSCENE||gameState==STATE_END){const t=ctx.canvasPostprocProgramInfo;e.bindFramebuffer(e.FRAMEBUFFER,null),e.bindTexture(e.TEXTURE_2D,ctx.canvasTex),e.useProgram(t.program),e.uniform2f(t.uRes,canvasW(),canvasH()),e.uniform1i(t.uTex,0),e.uniform1f(t.uTime,ctx.time),e.uniform1f(t.uEndFactor,player.endFactor||0),e.drawArrays(e.TRIANGLE_STRIP,0,4)}else if(gameState==STATE_GAME){e.bindFramebuffer(e.FRAMEBUFFER,ctx.fbTexData[0]);let t=ctx.programInfo;e.useProgram(t.program),e.uniform1f(t.uTime,ctx.time),e.uniform2f(t.uRes,ctx.fbTexData[2],ctx.fbTexData[3]),e.uniform2f(t.uPos,player.pos.x,player.pos.y),e.uniform2f(t.uSpeed,player.speed.x/player.maxVelocity,player.speed.y/player.maxVelocity),e.uniform4f(t.uCam,player.cam.x,player.cam.y,3*1.3,3),e.drawArrays(e.TRIANGLE_STRIP,0,4);let a=new Uint8Array(12);if(e.readPixels(0,0,3,1,e.RGBA,e.UNSIGNED_BYTE,a),e.bindFramebuffer(e.FRAMEBUFFER,null),t=ctx.postprocProgramInfo,e.bindTexture(e.TEXTURE_2D,ctx.fbTexData[1]),e.useProgram(t.program),e.uniform2f(t.uRes,canvasW(),canvasH()),e.uniform1i(t.uTex,0),e.uniform3f(t.uFactors,player.deathFactor,player.checkpointFactor,player.endFactor),e.drawArrays(e.TRIANGLE_STRIP,0,4),player.isEnd)return;a[0]>1?player.solidNormal=new Vec2(2*a[1]/255-1,2*a[2]/255-1):player.solidNormal=null;let o=a[8]>1;a[4]>1&&!o&&!player.isDead&&(player.isDead=!0,player.deathFactor=1,setTimeout(()=>{playerResurrect()},500),getAudioProcessor().death());let n=Math.round(a[9]);if(o&&n>=player.lastCheckpointId){if(255==n)return player.isEnd=!0,void getAudioProcessor().checkpoint();n>player.lastCheckpointId&&(player.checkpointFactor=1,getAudioProcessor().checkpoint()),player.lastCheckpointPos.set(player.pos.x,player.pos.y),player.lastCheckpointId=n}}}let cctx=document.querySelector("#canvas2d").getContext("2d");function setTextureCanvasData(){let e=ctx.gl;e.bindTexture(e.TEXTURE_2D,ctx.canvasTex),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,cctx.canvas)}function updateMenuCanvas(){let e=cctx.canvas.width,t=cctx.canvas.height,a=16*e/1200,o=4.1*a,n=4*a;cctx.clearRect(0,0,e,t),cctx.shadowBlur=.75*a;let c=(e,a)=>{cctx.font=cliFont,cctx.shadowColor=(cctx.fillStyle=a==gameSettings.currentSelection?"#9c4":"#999")+"b",cctx.fillText(e,o,t/2-3*n/2+n*a)};c("play",0),c("difficulty: "+gameSettings.difficultyVariants[gameSettings.difficulty],1),c("graphics: "+gameSettings.graphicsVariants[gameSettings.graphics],2),cctx.font=logoFont,cctx.shadowColor=cctx.fillStyle="#742",cctx.strokeStyle="#fa7",cctx.fillText(" >Ч  О  Ч<",e/2,t/2-a),cctx.strokeText("> Ч О Ч <",e/2,t/2-a),cctx.font=cliFont,cctx.fillText(" ..e.g.g.o.g..c.h.o.c.h..",e/2,t/2+a),setTextureCanvasData()}function showCutscene(e,t){let a=cctx.canvas.width,o=cctx.canvas.height;return cctx.clearRect(0,0,a,o),setTextureCanvasData(),print_2d(cctx,e(a,o),16*cctx.canvas.width/1200,()=>gameState!=t,setTextureCanvasData,()=>{getAudioProcessor().typingFn()})}function onResize(){gameState==STATE_MENU?updateMenuCanvas():gameState==STATE_GAME&&recreateGameFramebufferAndTex()}var ctx={};let canvasW=()=>ctx.canvas.clientWidth,canvasH=()=>ctx.canvas.clientHeight;function main(){var e=document.querySelector("#glcanvas"),t=e.getContext("webgl");handleResize(),ctx.canvas=e,ctx.gl=t;init(t,initScreenQuadBuffer(t)),loop()}function loop(){const e=ctx.gl;e.viewport(0,0,canvasW(),canvasH()),render(e),window.requestAnimationFrame(loop)}function handleResize(){["glcanvas","canvas2d"].forEach(e=>{const t=document.getElementById(e);t.width=window.innerWidth,t.height=window.innerHeight,em=Math.round(16*Math.min(t.width,t.height)/1200),document.querySelector("html").style.fontSize=em+"px",onResize()})}var keyFunction=(e,t)=>{e.repeat||onKeyEvent(e.which,t)};let joy;window.addEventListener("keydown",e=>keyFunction(e,1)),window.addEventListener("keyup",e=>keyFunction(e,0)),window.addEventListener("load",main,!1),window.addEventListener("resize",handleResize),window.setInterval(()=>update(),16);let joyDeadzone=.33;const AXIS=0,BUTTON=1;let layout=[[1,13,38],[1,16,39],[1,14,40],[1,15,37],[0,1,38],[0,16,39],[0,17,40],[0,0,37],[1,0,13],[1,1,13],[1,2,13],[1,3,13],[1,9,27]];function joyInput(e,t){layout.forEach(a=>{let o,[n,c,r,i]=a;if(n===BUTTON){let t=e.buttons[c];o=t&&t.pressed?1:0}else{let t=e.axes[c%16];o=t>0==c>15?Math.abs(t):0,o<joyDeadzone&&(o=0)}o!==i&&t(r,o?1:0),a[3]=o})}function onKeyEvent(e,t){let a=13==e&&t,o=[38,40,37,39,87,83,65,68,90,87,81,68].indexOf(e);if(o>=0&&(o%=4),gameState==STATE_MENU){if(t>0){if(0==gameSettings.currentSelection&&a&&(setState(STATE_START_CUTSCENE),getAudioProcessor().menuChangeFn(!0)),0==o||1==o){let e=3;gameSettings.currentSelection=(gameSettings.currentSelection+(1==o?1:e-1))%e,updateMenuCanvas(),getAudioProcessor().menuChangeFn(!1)}if(2==o||3==o)if(1==gameSettings.currentSelection){let e=gameSettings.difficultyVariants.length;gameSettings.difficulty=(gameSettings.difficulty+(3==o?1:e-1))%e,updateMenuCanvas(),getAudioProcessor().menuChangeFn(!0)}else if(2==gameSettings.currentSelection){let e=gameSettings.graphicsVariants.length;gameSettings.graphics=(gameSettings.graphics+(3==o?1:e-1))%e,updateMenuCanvas(),getAudioProcessor().menuChangeFn(!0)}}}else if(gameState==STATE_START_CUTSCENE)a&&setState(STATE_GAME);else if(gameState==STATE_END);else if(gameState==STATE_GAME){let a=player.movementStates;a[o]=t;let n=player.maxVelocity;player.reqSpeed.set((a[3]-a[2])*n,(a[0]-a[1])*n),27==e&&setState(STATE_MENU)}}window.addEventListener("gamepadconnected",e=>joy=e.gamepad);</script></body></html>